package com.caoustc.okhttplib.okhttp

import okhttp3.MediaType
import okhttp3.RequestBody
import okio.*
import java.io.IOException

class ProgressRequestBody(
    protected var requestBody: RequestBody?,
    protected var callback: OkHttpProgressCallback?
) : RequestBody() {
    interface OkHttpProgressCallback {
        fun updateProgress(progress: Int, networkSpeed: Long, done: Boolean)
    }

    private var previousTime: Long = 0
    protected var countingSink: CountingSink? = null
    override fun contentType(): MediaType? {
        return requestBody!!.contentType()
    }

    override fun contentLength(): Long {
        try {
            return requestBody!!.contentLength()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return -1
    }

    @Throws(IOException::class)
    override fun writeTo(sink: BufferedSink) {
        previousTime = System.currentTimeMillis()
        countingSink = CountingSink(sink)
        val bufferedSink = Okio.buffer(countingSink)
        requestBody!!.writeTo(bufferedSink)
        bufferedSink.flush()
    }

    protected inner class CountingSink(sink: Sink?) : ForwardingSink(sink) {
        private var bytesWritten = 0L
        var contentLength = 0L
        @Throws(IOException::class)
        override fun write(source: Buffer, byteCount: Long) {
            super.write(source, byteCount)
            if (contentLength == 0L) {
                contentLength = contentLength()
            }
            bytesWritten += byteCount
            if (callback != null) {
                var totalTime = (System.currentTimeMillis() - previousTime) / 1000
                if (totalTime == 0L) {
                    totalTime += 1
                }
                val networkSpeed = bytesWritten / totalTime
                val progress = (bytesWritten * 100 / contentLength).toInt()
                val done = bytesWritten == contentLength
                callback!!.updateProgress(progress, networkSpeed, done)
            }
        }
    }
}